package com.thh.datamonitor.executor;

import com.thh.common.utils.spring.SpringUtils;
import com.thh.datamonitor.annotation.DbType;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @ClassName db执行器工厂
 * @Desc
 * @Author tanhh
 * @Date 2022/6/27 15:24
 * @Version 1.0
 **/
@Component
public class DbExecutorFactory{
    private static final Map<String, AbstractDbExecutor> abstractDbExecutorMap = new ConcurrentHashMap<>();

    // 启动后执行
    @PostConstruct
    private synchronized void init() {
        Map<String, AbstractDbExecutor> allAbstractDbExecutorMap = SpringUtils.getBeansOfType(AbstractDbExecutor.class);
        allAbstractDbExecutorMap.forEach(
                (name, strategy) -> {
                    Optional<DbType> annotation = Optional.ofNullable(strategy.getClass().getAnnotation(DbType.class));
                    Class<? extends AbstractDbExecutor> clazz = strategy.getClass();
                    String packageName = clazz.getName();
                    if (packageName.contains("$$EnhancerByCGLIB$$") || packageName.contains("$$EnhancerBySpringCGLIB$$")) { // 如果是CGLIB动态生成的类
                        packageName = packageName.substring(0, packageName.indexOf("$$"));
                    }
                    String finalPackageName = packageName;
                    DbType dbType = annotation.orElseThrow(() -> new IllegalStateException("Error creating bean with name '" + finalPackageName + "'"));
                    abstractDbExecutorMap.putIfAbsent(dbType.value().getName(), strategy);
                });
    }


    public static AbstractDbExecutor getDbExecutor(String dbType) {
        // 判断策略是否存在
        if (!abstractDbExecutorMap.containsKey(dbType)) {
            throw new IllegalArgumentException("dbType not found");
        }
        // 获得策略实例
        // 执行策略
        return abstractDbExecutorMap.get(dbType);
    }
}
